package com.fablesoft.projectdatacollect.http;

import android.graphics.Bitmap;
import android.text.TextUtils;
import android.util.Log;

import com.fablesoft.projectdatacollect.MyApplication;
import com.fablesoft.projectdatacollect.bean.BaseImageRequest;
import com.fablesoft.projectdatacollect.bean.BaseResponse;
import com.fablesoft.projectdatacollect.bean.ItemFingerprint;
import com.fablesoft.projectdatacollect.bean.ItemMaterial;
import com.fablesoft.projectdatacollect.util.CommonUtils;
import com.fablesoft.projectdatacollect.util.Config;
import com.fablesoft.projectdatacollect.util.Log4jUtil;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 */
public final class HttpUploadImagesThread<T> extends Thread {
    /**
     * 日志标签
     */
    private static final String TAG = "HttpUploadImagesThread";

    /**
     * 用户控制是否中断请求的标志
     */
    private boolean cancel = false;

    /**
     * 请求url
     */
    private String url;

    /**
     * POST请求数据
     */
    private Map<String, Object> parms;

    /**
     * POST请求数据
     */
    private List<T> images;

    /**
     * HTTP请求监听的实现类，当请求有结果时会设置该类的相应方法
     */
    private HttpListener listener;

    private Class clazz;

    public HttpUploadImagesThread(String url, HttpListener listener, List<T> images,
                                  Map<String, Object> parms, Class clazz) {
        this.url = url;
        this.parms = parms;
        this.listener = listener;
        this.images = images;
        this.clazz = clazz;
    }

    /**
     * 发送HTTP请求，并将结果设置回HttpListener的实现类中
     */
    @Override
    public void run() {
        String result = null;
        result = sendRequest();

        // 如果用户还没有中断请求
        if (!cancel) {
            try {
                BaseResponse response = JsonUtil.getResponse(result, clazz);
                if (response != null && "403".equals(response.getCode())) {
                    listener.onNotLogin(response);
                } else {
                    listener.onRequestFinish(response);
                }
            } catch (Exception e) {
                Log4jUtil.e(e.toString());
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送请求获取响应
     *
     * @return
     * @see [类、类#方法、类#成员]
     */
    private String sendRequest() {
        Log.d(CommonUtils.TAG_UPLOAD, parms.toString());
        URL myURL = null;
        HttpURLConnection conn = null;
        InputStream is = null;
        BufferedInputStream in = null;
        DataOutputStream dos = null;
        StringBuffer response = new StringBuffer();
        String prefix = "--";
        String boundary = "*****";
        String end = "\r\n";
        try {
            Log.d(CommonUtils.TAG_UPLOAD, "upload url = " + url);
            myURL = new URL(url);
            conn = (HttpURLConnection) myURL.openConnection();
            /* 允许Input、Output，不使用Cache */
            conn.setDoInput(true);
            conn.setChunkedStreamingMode(4096);
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            /* 设置传送的method=POST */
            conn.setRequestMethod("POST");
			/* setRequestProperty */
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("Content-Type",
                    "multipart/form-data;charset=UTF-8;boundary=" + boundary);
            conn.setRequestProperty(Config.CLIENT_TYPE_KEY, Config.CLIENT_TYPE_VALUE);
            if (!TextUtils.isEmpty(MyApplication.getInstance().getSessionId())) {
                conn.setRequestProperty("Cookie", MyApplication.getInstance().getSessionId());
            }
			/* 设置DataOutputStream */
            dos = new DataOutputStream(conn.getOutputStream());
            if (parms != null) {
                for (Entry<String, Object> entry : parms.entrySet()) {
                    if (entry.getValue() != null && !TextUtils.isEmpty(entry.getValue().toString())) {
                        StringBuffer buf = new StringBuffer();
                        buf.append(prefix + boundary  + end);
                        buf.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + end);
                        buf.append(end);
                        buf.append(entry.getValue().toString());
                        buf.append(end);
                        dos.write(buf.toString().getBytes("UTF-8"));
                    }
                }
            }
            if (images == null || images.size() == 0) {
                Log.e(CommonUtils.TAG_UPLOAD, "files is null  or size is 0");
                return null;
            } else {
                Log.d(CommonUtils.TAG_UPLOAD, "size = " + images.size());
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                for (int i = 0; i < images.size(); i++) {
                    BaseImageRequest image = (BaseImageRequest) images.get(i);
                    StringBuffer b = new StringBuffer();
                    b.append(prefix + boundary + end);
                    b.append("Content-Disposition: form-data; "
                            + "name=\"file\";filename=" + image.getFileName() + ".jpg" + end);
                    b.append("Content-Type: application/octet-stream" + end);
                    b.append(end);
                    dos.write(b.toString().getBytes("UTF-8"));
//                    dos.writeBytes(prefix + boundary + end);
//                    dos.writeBytes("Content-Disposition: form-data; "
//                            + "name=\"file\";filename=" + image.getFileName() + ".jpg" + end);
//                    dos.writeBytes("Content-Type: application/octet-stream" + end);
//                    dos.writeBytes(end);
                    /* 取得文件的FileInputStream */
                    if (image instanceof ItemFingerprint) {
                        baos.reset();
                        image.getBitmap().compress(Bitmap.CompressFormat.JPEG, 100, baos);
                        in = new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray()));
                    } else if (image instanceof ItemMaterial) {
                        in = new BufferedInputStream(new FileInputStream(image.getLocalPath()));
                    }
//						fis = new FileInputStream(files.get(i));
						/* 设置每次写入1024bytes */
                    int bufferSize = 4096;
                    byte[] buffer = new byte[bufferSize];
                    int length = -1;
						/* 从文件读取数据至缓冲区 */
                    while ((length = in.read(buffer)) != -1) {
							/* 将资料写入DataOutputStream中 */
                        dos.write(buffer, 0, length);
                        Log.i("lzx", "write file");
                    }
                    dos.writeBytes(end);
                    Log.i("lzx", "write end");
                    in.close();
                    in = null;
                }
                baos.close();
            }
            dos.writeBytes(prefix + boundary + prefix + end);
            dos.writeBytes(end);
            dos.flush();
            Log.d(CommonUtils.TAG_UPLOAD, "upload response code = " + conn.getResponseCode());
			/* 取得Response内容 */
            if (conn.getResponseCode() == 200) {
                is = new BufferedInputStream(conn.getInputStream());
                byte[] buf = new byte[2048];
                is = conn.getInputStream();
                for (int n; (n = is.read(buf)) != -1; ) {
                    response.append(new String(buf, 0, n, "UTF-8"));
                }
                Log.d(CommonUtils.TAG_UPLOAD, "upload response = " + response.toString());
            } else {
                Log.e(CommonUtils.TAG_UPLOAD, "ResponseCode:" + conn.getResponseCode());
            }
        } catch (Exception e) {
            Log4jUtil.e(e.toString());
            response = null;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    Log4jUtil.e(e.toString());
                }
            }
            if (dos != null) {
                try {
                    dos.close();
                } catch (IOException e) {
                    Log4jUtil.e(e.toString());
                }
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    Log4jUtil.e(e.toString());
                }
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
        return response == null ? null : response.toString();
    }

}
